From: Julien Grall Date: Fri, 8 May 2015 17:01:12 +0000 (+0100) Subject: xen/arm: gic-v3: Implement correctly the callback send_SGI X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~3202 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success/%22http:/www.example.com/cgi/success?a=commitdiff_plain;h=8c1ed6d0c08c8139c42ce0a12121b268ea144a52;p=xen.git xen/arm: gic-v3: Implement correctly the callback send_SGI Currently, the GICv3 driver is only able to send an SGI when the cpumask is provided. Although with the modes SGI_TARGET_OTHERS and SGI_TARGET_SELF, no cpumask is provided. Any usage of those modes will crash the hypersivor. Rename gicv3_send_sgi to gicv3_send_sgi_list and implement the different modes: - SGI_TARGET_OTHERS: Set the Interrupt Routing Mode (bit 40) to 1 (see Table 4 on Section 4.2.6 PRD03-GENC-010745 24.0) - SGI_TARGET_SELF: Unlike GICv2, the GICv3 SGI registers don't provide a specific field. So use gicv3_send_sgi_list and pass the cpumask of the current CPU - SGI_TARGET_LIST: Directly call gicv3_send_sgi_list with the given cpumask Also, use WRITE_SYSREG64 to write into ICC_SGI1R_EL1 the access is 64-bit on all the architectures. Reported-by: Chen Baozi Signed-off-by: Julien Grall Tested-by: Chen Baozi Acked-by: Ian Campbell --- diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c index db498edce4..30682cf3c7 100644 --- a/xen/arch/arm/gic-v3.c +++ b/xen/arch/arm/gic-v3.c @@ -808,8 +808,7 @@ out: return tlist; } -static void gicv3_send_sgi(enum gic_sgi sgi, enum gic_sgi_mode mode, - const cpumask_t *cpumask) +static void gicv3_send_sgi_list(enum gic_sgi sgi, const cpumask_t *cpumask) { int cpu = 0; uint64_t val; @@ -833,12 +832,34 @@ static void gicv3_send_sgi(enum gic_sgi sgi, enum gic_sgi_mode mode, MPIDR_AFFINITY_LEVEL(cluster_id, 1) << 16 | tlist); - WRITE_SYSREG(val, ICC_SGI1R_EL1); + WRITE_SYSREG64(val, ICC_SGI1R_EL1); } /* Force above writes to ICC_SGI1R_EL1 */ isb(); } +static void gicv3_send_sgi(enum gic_sgi sgi, enum gic_sgi_mode mode, + const cpumask_t *cpumask) +{ + switch ( mode ) + { + case SGI_TARGET_OTHERS: + WRITE_SYSREG64(ICH_SGI_TARGET_OTHERS << ICH_SGI_IRQMODE_SHIFT | + (uint64_t)sgi << ICH_SGI_IRQ_SHIFT, + ICC_SGI1R_EL1); + isb(); + break; + case SGI_TARGET_SELF: + gicv3_send_sgi_list(sgi, cpumask_of(smp_processor_id())); + break; + case SGI_TARGET_LIST: + gicv3_send_sgi_list(sgi, cpumask); + break; + default: + BUG(); + } +} + /* Shut down the per-CPU GIC interface */ static void gicv3_disable_interface(void) { diff --git a/xen/include/asm-arm/gic_v3_defs.h b/xen/include/asm-arm/gic_v3_defs.h index b8a1c2eb62..556f114714 100644 --- a/xen/include/asm-arm/gic_v3_defs.h +++ b/xen/include/asm-arm/gic_v3_defs.h @@ -147,7 +147,7 @@ #define ICH_SGI_IRQMODE_SHIFT 40 #define ICH_SGI_IRQMODE_MASK 0x1 -#define ICH_SGI_TARGET_OTHERS 1 +#define ICH_SGI_TARGET_OTHERS 1UL #define ICH_SGI_TARGET_LIST 0 #define ICH_SGI_IRQ_SHIFT 24 #define ICH_SGI_IRQ_MASK 0xf